import gdp.stdlib.StdDraw;
import gdp.stdlib.StdOut;

public class Isogons {
	
	public static void main(String[] args) {
		
		int n = Integer.parseInt(args[0]); // Anzahl der auszugebenen Vielecke
		
		double myscale = 5.0; // Groeße der Zeichenebene in alle Richtungen
		
		// Gleichmaessige Anordnung
		double angle_diff = 360. / n;
		double angle = 0.0;
		double[] pos = new double[] { 3., 0 }; // alle Punkte sind Arrays mit
		// zwei Eintraegen
		
		StdDraw.setXscale(-myscale, myscale);
		StdDraw.setYscale(-myscale, myscale);
		
		for (int i = 0; i < n; i++, angle += angle_diff, pos = rotateP(angle_diff, pos)) {
			drawIsogon(3 + i, angle, pos); // Beginn mit Dreieck
		}
		
		StdDraw.show();
	}
	
	/**
	 * Verschiebt Menge von Punkten in 2D
	 *
	 * @param shift
	 *            2D Verschiebung als Array
	 * @param points
	 *            urspruengliche Punkte
	 * @return neue Punkte
	 */
	static double[][] translatePoints2D(double[] shift, double[][] points) {
		int length = points.length;
		double[][] newpoints = new double[length][2];
		
		// APPLY SHIFT
		
		for (int i = 0; i < length; i++) {
			newpoints[i][0] = (points[i][0] + shift[0]);
			newpoints[i][1] = (points[i][1] + shift[1]);
		}
		return newpoints;
	}
	
	/**
	 * Rotiert 2D-Punkt
	 *
	 * @param angle
	 *            Winkel 0...360
	 * @param point
	 *            Koordinaten des Punktes als Array
	 * @return Koordinaten des rotierten Punktes
	 */
	static double[] rotateP(double angle, double[] point) {
		double[] result = new double[2];
		
		// APPLY ROTATION
		
		result[0] = ((point[0] * Math.cos((angle * Math.PI) / 180)) - (point[1] * Math.sin((angle * Math.PI) / 180)));
		result[1] = ((point[0] * Math.sin((angle * Math.PI) / 180)) + (point[1] * Math.cos((angle * Math.PI) / 180)));
		
		return result;
	}
	
	/**
	 * Rotiert Menge von Punkten in 2D
	 *
	 * @param angle
	 *            Drehwinkel in Grad
	 * @param points
	 *            urspruengliche Punkte
	 * @return neue Punkte
	 */
	static double[][] rotatePoints2D(double angle, double[][] points) {
		int length = points.length;
		double[][] result = new double[length][2];
		
		// APPLY Rotation
		
		for (int i = 0; i < length; i++) {
			result[i] = rotateP(angle, points[i]);
		}
		return result;
	}
	
	/**
	 * Generiert Eckpunkte für Isogon mit n-Ecken auf Einhheitskreis. (ein
	 * n-Einheitspolygon) Isogone werden als Arrays ihrer Eckpunkte
	 * repraesentiert, um beim Zeichnen per StdDraw.polygon einen geschlossenen
	 * Polygonzug zu erhalten, muss der Anfangspunkt auch als Endpunkt erfasst
	 * werden !
	 *
	 * @param n
	 *            Ecken
	 * @return Eckpunkte
	 */
	static double[][] unit_isogon_points(int n) {
		
		double angle_diff = 360. / n;
		double[][] result = new double[n][2];
		double x = 0.0;
		double y = 0.0;
		double r = 1.0;
		for (int i = 0; i < n; i++) {
			
			result[i][0] = x + (r * Math.cos((i * Math.PI * angle_diff) / 180));
			result[i][1] = y + (r * Math.sin((i * Math.PI * angle_diff) / 180));
			
		}
		return result;
		
	}
	
	/**
	 * Generiert Eckpunkte für Isogon mit n Ecken, welches aus einem
	 * n-Einheitspolygon durch Drehung um angle und Verschiebung um shift
	 * hervorgeht
	 *
	 * @param n
	 *            Ecken
	 * @param angle
	 *            Drehung
	 * @param shift
	 *            Verschiebung
	 * @return Eckpunkte
	 */
	static double[][] isogon_points(int n, double angle, double[] shift) {
		double[][] result = new double[n][2];
		
		result = unit_isogon_points(n);
		// out("new ", 1);
		// out_points(result);
		
		result = rotatePoints2D(angle, result);
		// out("rotated ", 1);
		// out_points(result);
		
		result = translatePoints2D(shift, result);
		// out("shifted ", 1);
		// out_points(result);
		
		return result;
	}
	
	/**
	 * Wandelt die Eckpunkte eines Isogons (Array von Punkten) in das fuer die
	 * grafische Ausgabe (mittels StdDraw.polygon) noetige Format um
	 *
	 * @param points
	 *            die Ecken eines Isogons (als Punktpaare)
	 * @param index
	 *            0 - alle x-Koordinaten 1 - alle y-Koordinaten
	 * @return Array von x- oder y-Koordinaten
	 */
	static double[] getCoordinates(double[][] points, int index) {
		int l = points.length;
		double[] result = new double[l + 1];
		for (int i = 0; i < l; i++) {
			result[i] = points[i][index];
		}
		result[l] = points[0][index];
		return result;
	}
	
	/**
	 * Zeichnet ein Isogon mit n Ecken, welches aus dem n-Einheitspolygon durch
	 * Drehung um angle und Verschiebung um shift hervorgeht
	 *
	 * @param n
	 *            Ecken
	 * @param angle
	 *            Drehung
	 * @param shift
	 *            Verschiebung
	 * @return Eckpunkte
	 */
	static void drawIsogon(int n, double angle, double[] shift) {
		double[][] points = new double[n][2];
		
		points = isogon_points(n, angle, shift);
		StdDraw.polygon(getCoordinates(points, 0), getCoordinates(points, 1));
	}
	
	/**
	 * Ausdruck der Koordinaten
	 *
	 * @param points
	 */
	static void out_points(double[][] points) {
		int l = points.length;
		StdOut.print(l + " = ");
		for (int i = 0; i < l; i++) {
			StdOut.printf("%1d: (%1.3f,%1.3f)   ", i, points[i][0], points[i][1]);
		}
		StdOut.println("");
	}
	
	/**
	 *
	 * @param text
	 *            text to print
	 * @param n
	 *            0 print 1 println
	 */
	static void out(String text, int n) {
		if (n == 0) {
			StdOut.print(text);
		} else {
			StdOut.println(text);
		}
	}
	
}